package com.piece.module.spider.service;

import com.piece.core.framework.util.string.StringUtil;
import com.piece.core.jpa.repository.BaseService;
import com.piece.core.message.client.SmsClientFactory;
import com.piece.core.web.util.MailUtil;
import com.piece.module.spider.model.FlowNotice;
import com.piece.module.spider.model.SpiderFlow;
import com.piece.module.spider.response.FlowNoticeRepository;
import com.piece.module.spider.response.SpiderFlowRepository;
import com.piece.module.spider.support.FlowNoticeType;
import com.piece.module.spider.support.FlowNoticeWay;
import com.piece.module.spider.util.ExpressionUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Service
@RefreshScope
@Transactional
public class FlowNoticeService extends BaseService<FlowNotice, Long> {

    @Value("${spider.notice.subject:spider-flow流程通知}")
    private String subject;

    @Value("${spider.notice.content.start:#{null}}")
    private String startContext;

    @Value("${spider.notice.content.end:#{null}}")
    private String endContext;

    @Value("${spider.notice.content.exception:#{null}}")
    private String exceptionContext;

    @Value("${spider.notice.sms.template_code:#{null}}")
    private String templateCode;

    @Autowired
    private SmsClientFactory smsClientFactory;

    @Autowired
    private FlowNoticeRepository flowNoticeRepository;

    @Autowired
    private SpiderFlowRepository spiderFlowRepository;

    @PostConstruct
    public void initRepository() {
        super.setRepository(flowNoticeRepository);
    }

    @Override
    public FlowNotice insertOrUpdate(FlowNotice flowNotice) throws Exception {
        if (!spiderFlowRepository.checkExist(flowNotice.getId())) {
            throw new RuntimeException("没有找到对应的流程");
        }
        return super.insertOrUpdate(flowNotice);
    }

    /**
     * 发送对应的流程通知
     */
    public void sendFlowNotice(SpiderFlow spiderFlow, FlowNoticeType type) {
        FlowNotice notice = findById(spiderFlow.getId());
        if (null != notice && !StringUtil.isEmpty(notice.getRecipients()) && !StringUtil.isEmpty(notice.getNoticeWay())) {
            String content = null;
            String sendSubject = this.subject;
            switch (type) {
                case startNotice:
                    if (notice.judgeStartNotice()) {
                        content = startContext;
                        sendSubject += " - 流程开始执行";
                    }
                    break;
                case endNotice:
                    if (notice.judgeEndNotice()) {
                        content = endContext;
                        sendSubject += " - 流程执行完毕";
                    }
                    break;
                case exceptionNotice:
                    if (notice.judgeExceptionNotice()) {
                        content = exceptionContext;
                        sendSubject += " - 流程发生异常";
                    }
                    break;
            }
            if (StringUtil.isEmpty(content)) {
                return;
            }
            // 定义一个上下文变量
            Map<String, Object> variables = new HashMap<>();
            // 放入流程信息
            BeanMap beanMap = BeanMap.create(spiderFlow);
            for (Object key : beanMap.keySet()) {
                variables.put(key + "", beanMap.get(key));
            }
            // 放入当前时间
            variables.put("currentDate", this.getCurrentDate());
            content = ExpressionUtil.execute(content.replaceAll("[{]", "\\${"), variables) + "";
            // 整理收件人
            String recipients = notice.getRecipients();
            String[] recipient_arr;
            FlowNoticeWay way;
            for (String recipient : recipients.split(",")) {
                String noticeWay = notice.getNoticeWay();
                String people = recipient;
                // 如果含有":"证明单独配置了发送方式
                if (recipient.contains(":")) {
                    recipient_arr = recipient.split(":");
                    noticeWay = recipient_arr[0];
                    people = recipient_arr[1];
                }
                way = FlowNoticeWay.email;
                try {
                    way = FlowNoticeWay.valueOf(noticeWay);
                } catch (Exception e) {
                    log.error(e.getMessage(), e);
                }
                switch (way) {
                    case email:
                        MailUtil.getInstance().sendSimpleMail(people, sendSubject, content);
                        break;
                    case sms:
                        try {
                            smsClientFactory.getClient().sendSms(people, templateCode, null);
                        } catch (Exception e) {
                            log.error("发送爬虫短信通知失败：{}", e.getMessage());
                        }
                        break;
                }
            }
        }
    }

    private String getCurrentDate() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        return sdf.format(new Date());
    }
}
